package com.wahoyu.exportwordtest.service;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.io.FileUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.data.*;
import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy;
import com.wahoyu.exportwordtest.api.RemoteFileService;
import com.wahoyu.exportwordtest.domain.SaRunReport;
import com.wahoyu.exportwordtest.domain.User;
import com.wahoyu.exportwordtest.mapper.SaRunReportMapper;
import freemarker.template.TemplateException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 导出word文档
 */
@Service
@Slf4j
public class ExportWordService {

    @Value("${wordPath}")
    private String wordPath;

    @Autowired
    private EchartsService echartsService;

    @Autowired
    private ReportService reportService;

    @Autowired
    private HttpRequestService httpRequestService;

    @Autowired
    private MinioService minioService;

    @Autowired
    SaRunReportMapper saRunReportMapper;

    /**
     * 导出所有客户的运行报告
     * @author wanghongyu02
     * @Date 2025/4/23 14:02
     */
    public void exportAllWord() throws IOException {

        // 请求用户列表
        Map<String, String> reqMap = new HashMap<>();
        reqMap.put("reportId", "24c3c361b2e1679f75090df8466c5587");
        List<JSONObject> resultList = httpRequestService.getDataByFeign(reqMap, "请求客户列表");

        List<String> customerIdList = resultList.stream().map(item -> item.getString("customerId"))
                .distinct().collect(Collectors.toList());

        List<String> customerNameList = resultList.stream().map(item -> item.getString("customerName"))
                .distinct().collect(Collectors.toList());

        for (int i = 0; i < customerIdList.size(); i++) {
            this.exportOneWord(customerIdList.get(i), customerNameList.get(i));
        }
    }

    /**
     * 导出所有客户的运行报告
     * @author wanghongyu02
     * @Date 2025/4/23 14:02
     */
    public void testExportWord() throws IOException {
        this.exportOneWord(null, null);
    }


    /**
     * 导出单个客户的运行报告
     * @author wanghongyu02
     */
    public void exportOneWord(String customerId, String customerName) throws IOException {

        if (customerName == null) customerName = "";

        // 拿到最新的运行报告的地址 saRunReportUrl
        List<SaRunReport> saRunReportList = saRunReportMapper.selectList(new QueryWrapper<SaRunReport>()
                .orderByDesc("create_time")
                .eq("status", 1)
                .eq("file_type", "报告模板")
        );

        if (CollectionUtils.isEmpty(saRunReportList)) {
            throw new RuntimeException("当前无可用运行报告!");
        }

        String saRunReportUrl = saRunReportList.get(0).getFileUrl();

        // 请求file服务 获得 运行报告
        File file = minioService.downloadFile(saRunReportUrl);

//        // 拿到本地模板文件
//        File file = new File(wordPath + "word/doc/report.docx");

        // 将数据对应模板
        Map<String, Object> map = new HashMap<>();
        reportService.getReportData(map, customerId);

        // 行循环插件
        LoopRowTableRenderPolicy rowPolicy = new LoopRowTableRenderPolicy();

        Configure config = Configure.builder()
                .bind("netProductsList", rowPolicy)
                .bind("netDeviceList", rowPolicy)
                .bind("faultList", rowPolicy)
                .bind("activeList", rowPolicy)
                .bind("netLineTable", rowPolicy)
                .bind("mplsTable", rowPolicy)
                .bind("eLineTable", rowPolicy)
                .bind("customerReportTable", rowPolicy)
                .build();

        // 定义服务器本地保存路径（示例路径，需根据实际情况调整）
        String outputPath = wordPath + "word/doc/"; // 服务器本地目录
        String fileName = customerName + "运行报告-" + new DateTime().toString("yyyy-MM-dd-HH-mm-ss") + ".docx";
        File outputFile = new File(outputPath + fileName);

        // 确保目录存在，若不存在则创建
        if (!outputFile.getParentFile().exists()) {
            outputFile.getParentFile().mkdirs();
        }

        // 将文档写入服务器本地文件
        try (FileOutputStream out = new FileOutputStream(outputFile);
             XWPFTemplate template = XWPFTemplate.compile(file, config).render(map)) {

            template.write(out);
            System.out.println("文件已保存至服务器本地: " + outputFile.getAbsolutePath());

        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        // 将文档写入到minio并删除本地文件
        minioService.uploadFileToMinio(fileName, outputFile);
    }

    /**
     * 测试拿到echarts图片
     *
     * @throws IOException
     * @throws TemplateException
     * @author wanghongyu02
     * @Date 2025/4/18 15:51
     */
    public byte[] testEcharts() {

        // 定义x轴
        List<String> xList = Arrays.asList("苹果", "香蕉", "西瓜");

        // 定义y轴
        List<Integer> yList = Arrays.asList(3, 2, 1);

        byte[] imgByteData;

        // 创建option替换模板
        HashMap<String, Object> templateMap = new HashMap<>();
        templateMap.put("categories", JSON.toJSONString(xList));
        templateMap.put("values", JSON.toJSONString(yList));
        // 拿到option字符串
        try {
            imgByteData = echartsService.getEchartsImgBytes(templateMap, "option.ftl");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return imgByteData;
    }

    /**
     * 测试拿到无参数的echarts图片
     *
     * @throws IOException
     * @throws TemplateException
     * @author wanghongyu02
     * @Date 2025/4/18 15:51
     */
    public byte[] testEcharts2() {

        byte[] imgByteData;
        try {
            imgByteData = echartsService.getEchartsImgBytes(new HashMap<>(), "option1.ftl");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return imgByteData;
    }


    /**
     * 此方法用于测试导出word+echarts
     * @param response
     * @author wanghongyu02
     * @Date 2025/4/21 16:47
     * @throws IOException
     */
    public void exportWord(HttpServletResponse response) throws IOException {

        // 拿到本地模板文件
        File file = new File(wordPath + "word/doc/input.docx");

        // 拿到本地图片
        String imgPath = wordPath + "word/img/1.jpg";

        // 将数据填充到模板中
        Map<String, Object> map = new HashMap<>();

        // 普通文字替换，原来的样式并不会发生改变
        map.put("name", "张三");
        map.put("age", "20");
        map.put("edu", "本科");

        // 设置表格
        RowRenderData row0 = Rows.of("姓名", "年龄", "学历", "照片").textColor("ffffff").bgColor("4472C4").center().create();
        RowRenderData row1 = Rows.of("张三", "20", "本科").center().create();
        RowRenderData row2 = Rows.of("李四", "22", "本科").center().create();

        // 表格插入图片
        PictureRenderData pic = Pictures.ofLocal(imgPath).size(50, 50).create();
        row1.addCell(Cells.of(pic).create());
        row2.addCell(Cells.of(pic).create());

        TableRenderData tableRenderData = Tables.create(row0, row1);
        tableRenderData.addRow(row2);
        map.put("table", tableRenderData);

        // 图片  本地、流、url、bytes
        map.put("img", Pictures.ofLocal(imgPath).create());
        map.put("byteImg", Pictures.ofBytes(FileUtil.readBytes(imgPath)).size(200, 200).create());
        map.put("eChartImg", Pictures.ofBytes(this.testEcharts()).size(760, 410).create());
        map.put("eChartImg2", Pictures.ofBytes(this.testEcharts2()).size(760, 410).create());

        // 固定表头
        List<User> userList = new ArrayList<>();
        userList.add(new User("张三", 20, "成都"));
        userList.add(new User("李四", 21, "沈阳"));
        map.put("studentList", userList);

        // 测试组合循环
        List<Map<String, Object>> items_31 = new ArrayList<>();
        for (int i = 0; i < 3; i++) {
            HashMap<String, Object> itemMap = new HashMap<>();
            itemMap.put("text_31", "（" + (i+1) + "）、hihihi");
            itemMap.put("image_31",  Pictures.ofBytes(this.testEcharts()).size(760, 410).create());
            items_31.add(itemMap);
        }
        map.put("items_31", items_31);

        // 创建表格渲染策略，使用行循环进行动态表格填充
        Configure config = Configure.builder().bind("studentList", new LoopRowTableRenderPolicy()).build();

        // 创建template对象
        XWPFTemplate template = XWPFTemplate.compile(file, config).render(map);

        // 设置响应头
        response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
        response.setCharacterEncoding("utf-8");
        String fileName = java.net.URLEncoder.encode("export-" + new DateTime().toString("yyyy_MM_dd_HH_mm_ss") + ".docx", "UTF-8");
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName);

        // 将文件内容写入响应输出流
        try (OutputStream os = response.getOutputStream(); ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
            template.write(bos);
            byte[] bytes = bos.toByteArray();
            os.write(bytes);
            os.flush();
        } finally {
            template.close();
        }
    }
}